﻿using Logging;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;

namespace CommunicationLibrary
{
    public struct Variable
    {
        public Byte Adress_H;
        public Byte Adress_L;
        public String Name;
        public Byte NameLenght;
        public Byte DataLenght;
    };

    public class CommunicationHandler
    {

        private SortedDictionary<String, Variable> _Variables = new SortedDictionary<String, Variable>();

        private SerialPort _Port;

        public CommunicationHandler(string portName, int baudRate)
        {
            _Port = new SerialPort(portName, baudRate);
        }

        public CommunicationHandler(string portName)
            : this(portName, 9600) { }

        public void Open()
        {
            _Port.Open();
        }

        public void Close()
        {
            _Port.Close();
        }

        public Boolean IsOpen
        {
            get
            {
                return _Port.IsOpen;
            }
        }

        public void LoadVariables()
        {
            byte[] buffer = new byte[] { 5, 0 };
            _Port.Write(buffer, 0, buffer.Length);

            int variable_count = _Port.ReadByte();
            for (int i = 0; i < variable_count; i++)
            {
                Variable v = new Variable();
                v.Adress_H = (byte)_Port.ReadByte();
                v.Adress_L = (byte)_Port.ReadByte();
                v.DataLenght = (byte)_Port.ReadByte();
                v.NameLenght = (byte)_Port.ReadByte();
                v.Name = "";
                for (int j = 0; j < v.NameLenght; j++)
                {
                    v.Name += (char)_Port.ReadByte();
                }

                Logger.Log("NAME: " + v.Name, LogLevel.Info);
                Logger.Log("ADRESS_H: " + v.Adress_H, LogLevel.Info);
                Logger.Log("ADRESS_L: " + v.Adress_L, LogLevel.Info);
                Logger.Log("DATALENGHT: " + v.DataLenght, LogLevel.Info);

                _Variables.Add(v.Name, v);
            }
        }

        public byte[] ReadVariable(String name)
        {
            Variable v = _Variables[name];
            byte[] outbuffer = new byte[v.DataLenght];
            byte[] buffer = new byte[] { 1, 3, v.DataLenght, v.Adress_H, v.Adress_L };
            _Port.Write(buffer, 0, buffer.Length);
            _Port.Read(outbuffer, 0, v.DataLenght);
            Logger.Log("INPUT: " + BitConverter.ToString(outbuffer), LogLevel.Info);
            return outbuffer;
        }

        public void SetVariable(Variable v, byte[] value)
        {
            byte[] buffer = new byte[] { 2, 3, v.DataLenght, v.Adress_H, v.Adress_L };
            buffer = buffer.Concat(value).ToArray();
            _Port.Write(buffer, 0, buffer.Length);
        }
    }
}
